Skip to content

Add support for breakglass for immutable folders - #6774

Merged
andrewnester merged 21 commits into
mainfrom
feat/immutable/breakglass
Oct 27, 2026
Merged

andrewnester merged 21 commits into
mainfrom
feat/immutable/breakglass

Conversation

@andrewnester

@andrewnester andrewnester commented Sep 21, 2026 •

Copy link
Copy Markdown
Contributor

Changes

Add support for breakglass for immutable folders

Why

Immutable folders can be "break-glassed" in an emergency. In this case, CLI should prevent a normal deploy if the previously used snapshot was broken. With --force, it should allow to deploy to a new suffixed path and the deployments after should continue as normal

Tests

Added an acceptance test

@github-actions

github-actions Bot commented Sep 21, 2026 •

Copy link
Copy Markdown
Contributor

Approval status: pending

/acceptance/bundle/ - needs approval

11 files changed
Suggested: @denik
Also eligible: @janniklasrose, @pietern, @shreyas-goenka, @anton-107, @lennartkats-db

/bundle/ - needs approval

7 files changed
Suggested: @denik
Also eligible: @janniklasrose, @pietern, @shreyas-goenka, @anton-107, @lennartkats-db

General files (require maintainer)

4 files changed
Based on git history:

  • @denik -- recent work in libs/testserver/, .nextchanges/bundles/, bundle/direct/dresources/

Any maintainer (@anton-107, @denik, @pietern, @shreyas-goenka, @simonfaltum, @renaudhartert-db, @janniklasrose, @lennartkats-db, @rugpanov, @rclarey) can approve all areas.
See OWNERS for ownership rules.

@eng-dev-ecosystem-bot

eng-dev-ecosystem-bot commented Sep 21, 2026 •

Copy link
Copy Markdown
Collaborator

Integration test report

Commit: f5c8dc1

Run: 40500001039

Env ✅​pass 🙈​skip Time
✅​ aws linux-2core-8gb 302 18 5:30
✅​ aws-windows-latest-4core-16gb 304 16 7:31
✅​ azure linux-2core-8gb 301 18 5:40
✅​ azure-windows-latest-4core-16gb 303 16 5:02
✅​ gcp linux-2core-8gb 300 19 5:25
✅​ gcp-windows-latest-4core-16gb 302 17 7:33
Top 6 slowest tests (at least 2 minutes):
duration env testname
5:45 gcp-windows-latest-4core-16gb TestAccept
4:55 aws-windows-latest-4core-16gb TestAccept
3:05 azure-windows-latest-4core-16gb TestAccept
2:58 gcp linux-2core-8gb TestAccept
2:56 azure linux-2core-8gb TestAccept
2:48 aws linux-2core-8gb TestAccept

Comment thread .nextchanges/bundles/immutable-breakglass.md Outdated
return 0, nil
}

entry, ok := b.DeploymentBundle.StateDB.GetResourceEntry(resources.SnapshotKey)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This reads state and makes a determination. Shouldn't that live in a DoRead of the snapshot?

I.e. seeing a different generation, or a "broken_glass: true" on DoRead can trigger recreation.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are a couple of blockers why it is not in DoRead, mainly the --force flag, which is not available at the resource level

It's also conceptually similar to existing CheckDashboardsModifiedRemotely check we have

Comment thread libs/snapshot/client.go
// ContentSubdir is the fixed subfolder the snapshot API appends to a caller-supplied
// relative_path to form the immutable content path (e.g. "<root>/<relative_path>/snapshot").
// The content path is what the create API echoes back and what InspectSnapshot inspects.
const ContentSubdir = "snapshot"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why does this happen?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's related to the fact that when we upload zip, we create 2 folders: one snapshot which can be broken glass and one is .internal which is not and contains a break glass marker and some other metadata

Comment thread libs/snapshot/client.go Outdated
@andrewnester
andrewnester requested review from a team as code owners September 25, 2026 10:11
@github-actions github-actions Bot added the DABs DABs related issues label Sep 25, 2026
Comment thread bundle/deploy/snapshot/upload.go
Comment thread libs/snapshot/client.go Outdated
@andrewnester
andrewnester requested a review from pietern October 13, 2026 15:14
@github-actions

github-actions Bot commented Oct 20, 2026 •

Copy link
Copy Markdown
Contributor

Commit: f5c8dc1e9 | Workflow run

Regression test report

Selected 13 changed tests (limit=20, 0 not selected)

17 tests: regression=17 unreleased=0 coverage=0 failing=0

test branch main (accb3df) latest (v1.22.1)
TestAccept/bundle/deploy/immutable/basic/DMS= ✅ ❌ ❌
TestAccept/bundle/deploy/immutable/breakglass/DMS= ✅ ❌ ❌
TestAccept/bundle/deploy/immutable/can-manage/DMS= ✅ ❌ ❌
TestAccept/bundle/deploy/immutable/destroy-redeploy/DMS= ✅ ❌ ❌
TestAccept/bundle/deploy/immutable/dev-mode/DMS= ✅ ❌ ❌
TestAccept/bundle/deploy/immutable/legacy-state/DMS= ✅ ❌ ❌
TestAccept/bundle/deploy/immutable/missing-snapshot/DMS= ✅ ❌ ❌
TestAccept/bundle/deploy/immutable/no-artifacts/DMS=/READPLAN= ✅ ❌ ❌
TestAccept/bundle/deploy/immutable/no-artifacts/DMS=/READPLAN=1 ✅ ❌ ❌
TestAccept/bundle/deploy/immutable/permissions-change/DMS= ✅ ❌ ❌
TestAccept/bundle/deploy/immutable/select/DMS= ✅ ❌ ❌
TestAccept/bundle/dms/immutable-folder/DMS=true/READPLAN= ✅ ❌ ❌
TestAccept/bundle/dms/immutable-folder/DMS=true/READPLAN=1 ✅ ❌ ❌
TestAccept/bundle/refschema/DMS= ✅ ❌ ❌
TestAccept/bundle/refschema/DMS=true ✅ ❌ ❌
TestAccept/bundle/resources/apps/immutable/DMS= ✅ ❌ ❌
TestAccept/bundle/resources/apps/immutable/DMS=true ✅ ❌ ❌
TestAccept/bundle/deploy/immutable/basic/DMS=: branch ✅ | main (accb3df) ❌ | latest (v1.22.1) ❌

main (accb3df):

acceptance_test.go:1311: Diff:
        --- bundle/deploy/immutable/basic/output.txt
        +++ /tmp/TestAcceptbundledeployimmutablebasicDMS=4288339869/002/output.txt
        @@ -15,7 +15,7 @@
         [
           {
             "notebook_task": {
        -      "notebook_path": "/Workspace/Users/[UUID]/.snapshots/[SNAPSHOT_HASH]/[SNAPSHOT_HASH]-[UUID]/snapshot/files/src/notebook"
        +      "notebook_path": "/Workspace/Users/[UUID]/.snapshots/[SNAPSHOT_HASH]/[SNAPSHOT_HASH]/files/src/notebook"
             },
             "task_key": "notebook_task"
           },
        @@ -30,7 +30,7 @@
           {
             "environment_key": "env",
             "spark_python_task": {
        -      "python_file": "/Workspace/Users/[UUID]/.snapshots/[SNAPSHOT_HASH]/[SNAPSHOT_HASH]-[UUID]/snapshot/files/src/main.py"
        +      "python_file": "/Workspace/Users/[UUID]/.snapshots/[SNAPSHOT_HASH]/[SNAPSHOT_HASH]/files/src/main.py"
             },
             "task_key": "spark_python_task"
           }
        @@ -42,7 +42,7 @@
             "environment_key": "env",
             "spec": {
               "dependencies": [
        -        "/Workspace/Users/[UUID]/.snapshots/[SNAPSHOT_HASH]/[SNAPSHOT_HASH]-[UUID]/snapshot/artifacts/.internal/immutable-0.0.1-py3-none-any.whl"
        +        "/Workspace/Users/[UUID]/.snapshots/[SNAPSHOT_HASH]/[SNAPSHOT_HASH]/artifacts/.internal/immutable-0.0.1-py3-none-any.whl"
               ],
               "environment_version": "4"
             }
        @@ -54,8 +54,8 @@
           "action": "create",
           "new_state": {
             "value": {
        -      "relative_path": "[SNAPSHOT_HASH]/[SNAPSHOT_HASH]-[UUID]",
        -      "full_path": "/Workspace/Users/[UUID]/.snapshots/[SNAPSHOT_HASH]/[SNAPSHOT_HASH]-[UUID]/snapshot",
        +      "relative_path": "[SNAPSHOT_HASH]/[SNAPSHOT_HASH]",
        +      "full_path": "/Workspace/Users/[UUID]/.snapshots/[SNAPSHOT_HASH]/[SNAPSHOT_HASH]",
               "bundle_id": "[SNAPSHOT_HASH]",
               "acl": [
                 {
        @@ -63,142 +63,27 @@
                   "permission_level": "CAN_READ"
                 }
               ],
        -      "can_manage": [
        -        {
        -          "service_principal_name": "[USERNAME]"
        -        }
        -      ],
        -      "zip_path": "[TEST_TMP_DIR]/.databricks/bundle/default/snapshots/[SNAPSHOT_HASH]-[UUID].zip"
        +      "zip_path": "[TEST_TMP_DIR]/.databricks/bundle/default/snapshots/[SNAPSHOT_HASH].zip"
             }
           }
         }
         
         >>> [CLI] bundle deploy
         Building python_artifact...
        -Created internal_immutable_snapshots.immutable
        -Created jobs.my_job
        -Files: 0 uploaded, 0 deleted
        -Resources: 2 created, 0 changed, 0 deleted, 0 unchanged
        +Error: cannot create resources.internal_immutable_snapshots.immutable: snapshot upload: No stub found for pattern: POST /api/2.0/repos/snapshots (501 <nil>)
         
        ->>> jq .settings.tasks job.json
        -"/Workspace/Users/[UUID]/.snapshots/[SNAPSHOT_HASH]/[SNAPSHOT_HASH]-[UUID]/snapshot/files/src/main.py"
        +Endpoint: POST [DATABRICKS_URL]/api/2.0/repos/snapshots
        +HTTP Status: 501 Not Implemented
        +API error_code: <nil>
        +API message: No stub found for pattern: POST /api/2.0/repos/snapshots
         
        ->>> jq .settings.tasks job.json
        -"/Workspace/Users/[UUID]/.snapshots/[SNAPSHOT_HASH]/[SNAPSHOT_HASH]-[UUID]/snapshot/files/src/notebook"
        +Error: cannot create resources.jobs.my_job: dependency failed: resources.internal_immutable_snapshots.immutable
         
        ->>> jq .settings.environments[0].spec.dependencies job.json
        -[
        -  "/Workspace/Users/[UUID]/.snapshots/[SNAPSHOT_HASH]/[SNAPSHOT_HASH]-[UUID]/snapshot/artifacts/.internal/immutable-0.0.1-py3-none-any.whl"
        -]
        -
        ->>> title Check snapshot plan after deploy
        -
        -=== Check snapshot plan after deploy
        ->>> [CLI] bundle plan -o json
        -Building python_artifact...
        -
        ->>> jq .plan["resources.internal_immutable_snapshots.immutable"] plan.json
        -{
        -  "action": "recreate",
        -  "new_state": {
        -    "value": {
        -      "relative_path": "[SNAPSHOT_HASH]/[SNAPSHOT_HASH]-[UUID]",
        -      "full_path": "/Workspace/Users/[UUID]/.snapshots/[SNAPSHOT_HASH]/[SNAPSHOT_HASH]-[UUID]/snapshot",
        -      "bundle_id": "[SNAPSHOT_HASH]",
        -      "acl": [
        -        {
        -          "user_name": "[USERNAME]",
        -          "permission_level": "CAN_READ"
        -        }
        -      ],
        -      "can_manage": [
        -        {
        -          "service_principal_name": "[USERNAME]"
        -        }
        -      ],
        -      "zip_path": "[TEST_TMP_DIR]/.databricks/bundle/default/snapshots/[SNAPSHOT_HASH]-[UUID].zip"
        -    }
        -  },
        -  "remote_state": {
        -    "relative_path": "[SNAPSHOT_HASH]/[SNAPSHOT_HASH]-[UUID]",
        -    "full_path": "/Workspace/Users/[UUID]/.snapshots/[SNAPSHOT_HASH]/[SNAPSHOT_HASH]-[UUID]/snapshot"
        -  },
        -  "changes": {
        -    "acl": {
        -      "action": "skip",
        -      "reason": "missing_in_remote",
        -      "old": [
        -        {
        -          "user_name": "[USERNAME]",
        -          "permission_level": "CAN_READ"
        -        }
        -      ],
        -      "new": [
        -        {
        -          "user_name": "[USERNAME]",
        -          "permission_level": "CAN_READ"
        -        }
        -      ],
        -      "remote": null
        -    },
        -    "bundle_id": {
        -      "action": "skip",
        -      "reason": "missing_in_remote",
        -      "old": "[SNAPSHOT_HASH]",
        -      "new": "[SNAPSHOT_HASH]",
        -      "remote": ""
        -    },
        -    "can_manage": {
        -      "action": "skip",
        -      "reason": "missing_in_remote",
        -      "old": [
        -        {
        -          "service_principal_name": "[USERNAME]"
        -        }
        -      ],
        -      "new": [
        -        {
        -          "service_principal_name": "[USERNAME]"
        -        }
        -      ]
        -    },
        -    "full_path": {
        -      "action": "recreate",
        -      "reason": "immutable",
        -      "old": "/Workspace/Users/[UUID]/.snapshots/[SNAPSHOT_HASH]/[SNAPSHOT_HASH]-[UUID]/snapshot",
        -      "new": "/Workspace/Users/[UUID]/.snapshots/[SNAPSHOT_HASH]/[SNAPSHOT_HASH]-[UUID]/snapshot",
        -      "remote": "/Workspace/Users/[UUID]/.snapshots/[SNAPSHOT_HASH]/[SNAPSHOT_HASH]-[UUID]/snapshot"
        -    },
        -    "relative_path": {
        -      "action": "recreate",
        -      "reason": "immutable",
        -      "old": "[SNAPSHOT_HASH]/[SNAPSHOT_HASH]-[UUID]",
        -      "new": "[SNAPSHOT_HASH]/[SNAPSHOT_HASH]-[UUID]",
        -      "remote": "[SNAPSHOT_HASH]/[SNAPSHOT_HASH]-[UUID]"
        -    },
        -    "zip_path": {
        -      "action": "recreate",
        -      "reason": "immutable",
        -      "old": "[TEST_TMP_DIR]/.databricks/bundle/default/snapshots/[SNAPSHOT_HASH]-[UUID].zip",
        -      "new": "[TEST_TMP_DIR]/.databricks/bundle/default/snapshots/[SNAPSHOT_HASH]-[UUID].zip",
        -      "remote": ""
        -    }
        -  }
        -}
        -
        ->>> [CLI] bundle deploy
        -Building python_artifact...
        -Recreated internal_immutable_snapshots.immutable
        -Updated jobs.my_job
         Files: 0 uploaded, 0 deleted
        -Resources: 1 created, 1 changed, 1 deleted, 0 unchanged
         
        -=== Check that job uses a new snapshot: Snapshot changed as expected
        -
         >>> [CLI] bundle destroy --auto-approve
        -The following resources will be deleted:
        -  delete resources.jobs.my_job
        -
         All files and directories at the following location will be deleted: /Workspace/Users/[USERNAME]/.bundle/test-bundle-immutable-[UNIQUE_NAME]/default
         
        -Destroy: 1 deleted
        +Destroy: 0 deleted
        +
        +Exit code: 1
        
    acceptance_test.go:1130: Test produced unexpected files:
        plan.json

latest (v1.22.1):

acceptance_test.go:1311: Diff:
        --- bundle/deploy/immutable/basic/output.txt
        +++ /tmp/TestAcceptbundledeployimmutablebasicDMS=2235004631/002/output.txt
        @@ -15,7 +15,7 @@
         [
           {
             "notebook_task": {
        -      "notebook_path": "/Workspace/Users/[UUID]/.snapshots/[SNAPSHOT_HASH]/[SNAPSHOT_HASH]-[UUID]/snapshot/files/src/notebook"
        +      "notebook_path": "/Workspace/Users/[UUID]/.snapshots/[SNAPSHOT_HASH]/[SNAPSHOT_HASH]/files/src/notebook"
             },
             "task_key": "notebook_task"
           },
        @@ -30,7 +30,7 @@
           {
             "environment_key": "env",
             "spark_python_task": {
        -      "python_file": "/Workspace/Users/[UUID]/.snapshots/[SNAPSHOT_HASH]/[SNAPSHOT_HASH]-[UUID]/snapshot/files/src/main.py"
        +      "python_file": "/Workspace/Users/[UUID]/.snapshots/[SNAPSHOT_HASH]/[SNAPSHOT_HASH]/files/src/main.py"
             },
             "task_key": "spark_python_task"
           }
        @@ -42,7 +42,7 @@
             "environment_key": "env",
             "spec": {
               "dependencies": [
        -        "/Workspace/Users/[UUID]/.snapshots/[SNAPSHOT_HASH]/[SNAPSHOT_HASH]-[UUID]/snapshot/artifacts/.internal/immutable-0.0.1-py3-none-any.whl"
        +        "/Workspace/Users/[UUID]/.snapshots/[SNAPSHOT_HASH]/[SNAPSHOT_HASH]/artifacts/.internal/immutable-0.0.1-py3-none-any.whl"
               ],
               "environment_version": "4"
             }
        @@ -54,8 +54,8 @@
           "action": "create",
           "new_state": {
             "value": {
        -      "relative_path": "[SNAPSHOT_HASH]/[SNAPSHOT_HASH]-[UUID]",
        -      "full_path": "/Workspace/Users/[UUID]/.snapshots/[SNAPSHOT_HASH]/[SNAPSHOT_HASH]-[UUID]/snapshot",
        +      "relative_path": "[SNAPSHOT_HASH]/[SNAPSHOT_HASH]",
        +      "full_path": "/Workspace/Users/[UUID]/.snapshots/[SNAPSHOT_HASH]/[SNAPSHOT_HASH]",
               "bundle_id": "[SNAPSHOT_HASH]",
               "acl": [
                 {
        @@ -63,142 +63,27 @@
                   "permission_level": "CAN_READ"
                 }
               ],
        -      "can_manage": [
        -        {
        -          "service_principal_name": "[USERNAME]"
        -        }
        -      ],
        -      "zip_path": "[TEST_TMP_DIR]/.databricks/bundle/default/snapshots/[SNAPSHOT_HASH]-[UUID].zip"
        +      "zip_path": "[TEST_TMP_DIR]/.databricks/bundle/default/snapshots/[SNAPSHOT_HASH].zip"
             }
           }
         }
         
         >>> [CLI] bundle deploy
         Building python_artifact...
        -Created internal_immutable_snapshots.immutable
        -Created jobs.my_job
        -Files: 0 uploaded, 0 deleted
        -Resources: 2 created, 0 changed, 0 deleted, 0 unchanged
        +Error: cannot create resources.internal_immutable_snapshots.immutable: snapshot upload: No stub found for pattern: POST /api/2.0/repos/snapshots (501 <nil>)
         
        ->>> jq .settings.tasks job.json
        -"/Workspace/Users/[UUID]/.snapshots/[SNAPSHOT_HASH]/[SNAPSHOT_HASH]-[UUID]/snapshot/files/src/main.py"
        +Endpoint: POST [DATABRICKS_URL]/api/2.0/repos/snapshots
        +HTTP Status: 501 Not Implemented
        +API error_code: <nil>
        +API message: No stub found for pattern: POST /api/2.0/repos/snapshots
         
        ->>> jq .settings.tasks job.json
        -"/Workspace/Users/[UUID]/.snapshots/[SNAPSHOT_HASH]/[SNAPSHOT_HASH]-[UUID]/snapshot/files/src/notebook"
        +Error: cannot create resources.jobs.my_job: dependency failed: resources.internal_immutable_snapshots.immutable
         
        ->>> jq .settings.environments[0].spec.dependencies job.json
        -[
        -  "/Workspace/Users/[UUID]/.snapshots/[SNAPSHOT_HASH]/[SNAPSHOT_HASH]-[UUID]/snapshot/artifacts/.internal/immutable-0.0.1-py3-none-any.whl"
        -]
        -
        ->>> title Check snapshot plan after deploy
        -
        -=== Check snapshot plan after deploy
        ->>> [CLI] bundle plan -o json
        -Building python_artifact...
        -
        ->>> jq .plan["resources.internal_immutable_snapshots.immutable"] plan.json
        -{
        -  "action": "recreate",
        -  "new_state": {
        -    "value": {
        -      "relative_path": "[SNAPSHOT_HASH]/[SNAPSHOT_HASH]-[UUID]",
        -      "full_path": "/Workspace/Users/[UUID]/.snapshots/[SNAPSHOT_HASH]/[SNAPSHOT_HASH]-[UUID]/snapshot",
        -      "bundle_id": "[SNAPSHOT_HASH]",
        -      "acl": [
        -        {
        -          "user_name": "[USERNAME]",
        -          "permission_level": "CAN_READ"
        -        }
        -      ],
        -      "can_manage": [
        -        {
        -          "service_principal_name": "[USERNAME]"
        -        }
        -      ],
        -      "zip_path": "[TEST_TMP_DIR]/.databricks/bundle/default/snapshots/[SNAPSHOT_HASH]-[UUID].zip"
        -    }
        -  },
        -  "remote_state": {
        -    "relative_path": "[SNAPSHOT_HASH]/[SNAPSHOT_HASH]-[UUID]",
        -    "full_path": "/Workspace/Users/[UUID]/.snapshots/[SNAPSHOT_HASH]/[SNAPSHOT_HASH]-[UUID]/snapshot"
        -  },
        -  "changes": {
        -    "acl": {
        -      "action": "skip",
        -      "reason": "missing_in_remote",
        -      "old": [
        -        {
        -          "user_name": "[USERNAME]",
        -          "permission_level": "CAN_READ"
        -        }
        -      ],
        -      "new": [
        -        {
        -          "user_name": "[USERNAME]",
        -          "permission_level": "CAN_READ"
        -        }
        -      ],
        -      "remote": null
        -    },
        -    "bundle_id": {
        -      "action": "skip",
        -      "reason": "missing_in_remote",
        -      "old": "[SNAPSHOT_HASH]",
        -      "new": "[SNAPSHOT_HASH]",
        -      "remote": ""
        -    },
        -    "can_manage": {
        -      "action": "skip",
        -      "reason": "missing_in_remote",
        -      "old": [
        -        {
        -          "service_principal_name": "[USERNAME]"
        -        }
        -      ],
        -      "new": [
        -        {
        -          "service_principal_name": "[USERNAME]"
        -        }
        -      ]
        -    },
        -    "full_path": {
        -      "action": "recreate",
        -      "reason": "immutable",
        -      "old": "/Workspace/Users/[UUID]/.snapshots/[SNAPSHOT_HASH]/[SNAPSHOT_HASH]-[UUID]/snapshot",
        -      "new": "/Workspace/Users/[UUID]/.snapshots/[SNAPSHOT_HASH]/[SNAPSHOT_HASH]-[UUID]/snapshot",
        -      "remote": "/Workspace/Users/[UUID]/.snapshots/[SNAPSHOT_HASH]/[SNAPSHOT_HASH]-[UUID]/snapshot"
        -    },
        -    "relative_path": {
        -      "action": "recreate",
        -      "reason": "immutable",
        -      "old": "[SNAPSHOT_HASH]/[SNAPSHOT_HASH]-[UUID]",
        -      "new": "[SNAPSHOT_HASH]/[SNAPSHOT_HASH]-[UUID]",
        -      "remote": "[SNAPSHOT_HASH]/[SNAPSHOT_HASH]-[UUID]"
        -    },
        -    "zip_path": {
        -      "action": "recreate",
        -      "reason": "immutable",
        -      "old": "[TEST_TMP_DIR]/.databricks/bundle/default/snapshots/[SNAPSHOT_HASH]-[UUID].zip",
        -      "new": "[TEST_TMP_DIR]/.databricks/bundle/default/snapshots/[SNAPSHOT_HASH]-[UUID].zip",
        -      "remote": ""
        -    }
        -  }
        -}
        -
        ->>> [CLI] bundle deploy
        -Building python_artifact...
        -Recreated internal_immutable_snapshots.immutable
        -Updated jobs.my_job
         Files: 0 uploaded, 0 deleted
        -Resources: 1 created, 1 changed, 1 deleted, 0 unchanged
         
        -=== Check that job uses a new snapshot: Snapshot changed as expected
        -
         >>> [CLI] bundle destroy --auto-approve
        -The following resources will be deleted:
        -  delete resources.jobs.my_job
        -
         All files and directories at the following location will be deleted: /Workspace/Users/[USERNAME]/.bundle/test-bundle-immutable-[UNIQUE_NAME]/default
         
        -Destroy: 1 deleted
        +Destroy: 0 deleted
        +
        +Exit code: 1
        
    acceptance_test.go:1130: Test produced unexpected files:
        plan.json
FAIL
TestAccept/bundle/deploy/immutable/breakglass/DMS=: branch ✅ | main (accb3df) ❌ | latest (v1.22.1) ❌

main (accb3df):

acceptance_test.go:1311: Diff:
        --- bundle/deploy/immutable/breakglass/output.txt
        +++ /tmp/TestAcceptbundledeployimmutablebreakglassDMS=3735195601/002/output.txt
        @@ -1,63 +1,20 @@
         
         === Deploy the immutable snapshot
         >>> [CLI] bundle deploy
        -Created internal_immutable_snapshots.immutable
        -Created jobs.my_job
        -Files: 0 uploaded, 0 deleted
        -Resources: 2 created, 0 changed, 0 deleted, 0 unchanged
        -First snapshot path: /Workspace/Users/[UUID]/.snapshots/[SNAPSHOT_HASH]/[SNAPSHOT_HASH]-[UUID]/snapshot/files/src/main.py
        +Error: cannot create resources.internal_immutable_snapshots.immutable: snapshot upload: No stub found for pattern: POST /api/2.0/repos/snapshots (501 <nil>)
         
        -=== Break the glass out of band
        ->>> [CLI] api post /api/2.0/snapshots:breakGlass --json {"snapshot_content_path": "/Workspace/Users/[UUID]/.snapshots/[SNAPSHOT_HASH]/[SNAPSHOT_HASH]-[UUID]/snapshot"}
        -true
        +Endpoint: POST [DATABRICKS_URL]/api/2.0/repos/snapshots
        +HTTP Status: 501 Not Implemented
        +API error_code: <nil>
        +API message: No stub found for pattern: POST /api/2.0/repos/snapshots
         
        -=== Deploy without --force fails
        ->>> musterr [CLI] bundle deploy
        -Error: the last deployment was modified in the workspace. Changes might be overwritten by this deployment. To confirm it, use the --force flag
        +Error: cannot create resources.jobs.my_job: dependency failed: resources.internal_immutable_snapshots.immutable
         
         Files: 0 uploaded, 0 deleted
         
        -=== Deploy with --force moves to a new snapshot
        ->>> [CLI] bundle deploy --force
        -Recreated internal_immutable_snapshots.immutable
        -Updated jobs.my_job
        -Files: 0 uploaded, 0 deleted
        -Resources: 1 created, 1 changed, 1 deleted, 0 unchanged
        -Second snapshot path: /Workspace/Users/[UUID]/.snapshots/[SNAPSHOT_HASH]/[SNAPSHOT_HASH]-[UUID]/snapshot/files/src/main.py
        -OK: --force created a new snapshot path
        -
        -=== Redeploy reuses the new snapshot
        ->>> [CLI] bundle deploy
        -Files: 0 uploaded, 0 deleted
        -Resources: 0 created, 0 changed, 0 deleted, 2 unchanged
        -Third snapshot path: /Workspace/Users/[UUID]/.snapshots/[SNAPSHOT_HASH]/[SNAPSHOT_HASH]-[UUID]/snapshot/files/src/main.py
        -OK: new snapshot reused on redeploy
        -
        -=== Save a plan for a content change, then break the glass before deploying it
        ->>> [CLI] bundle plan -o json
        -
        ->>> [CLI] api post /api/2.0/snapshots:breakGlass --json {"snapshot_content_path": "/Workspace/Users/[UUID]/.snapshots/[SNAPSHOT_HASH]/[SNAPSHOT_HASH]-[UUID]/snapshot"}
        -true
        -
        -=== Deploying the saved plan without --force fails
        ->>> musterr [CLI] bundle deploy --plan plan.json
        -Error: the last deployment was modified in the workspace. Changes might be overwritten by this deployment. To confirm it, use the --force flag
        -
        -Files: 0 uploaded, 0 deleted
        -
        -=== Deploying the saved plan with --force moves to the planned snapshot
        ->>> [CLI] bundle deploy --plan plan.json --force
        -Recreated internal_immutable_snapshots.immutable
        -Updated jobs.my_job
        -Files: 0 uploaded, 0 deleted
        -Resources: 1 created, 1 changed, 1 deleted, 0 unchanged
        -Fourth snapshot path: /Workspace/Users/[UUID]/.snapshots/[SNAPSHOT_HASH]/[SNAPSHOT_HASH]-[UUID]/snapshot/files/src/main.py
        -OK: the saved plan moved the deployment to a new snapshot
        -
         >>> [CLI] bundle destroy --auto-approve
        -The following resources will be deleted:
        -  delete resources.jobs.my_job
        -
         All files and directories at the following location will be deleted: /Workspace/Users/[USERNAME]/.bundle/test-bundle-immutable-breakglass-[UNIQUE_NAME]/default
         
        -Destroy: 1 deleted
        +Destroy: 0 deleted
        +
        +Exit code: 1
        
FAIL

latest (v1.22.1):

acceptance_test.go:1311: Diff:
        --- bundle/deploy/immutable/breakglass/output.txt
        +++ /tmp/TestAcceptbundledeployimmutablebreakglassDMS=2817202445/002/output.txt
        @@ -1,63 +1,20 @@
         
         === Deploy the immutable snapshot
         >>> [CLI] bundle deploy
        -Created internal_immutable_snapshots.immutable
        -Created jobs.my_job
        -Files: 0 uploaded, 0 deleted
        -Resources: 2 created, 0 changed, 0 deleted, 0 unchanged
        -First snapshot path: /Workspace/Users/[UUID]/.snapshots/[SNAPSHOT_HASH]/[SNAPSHOT_HASH]-[UUID]/snapshot/files/src/main.py
        +Error: cannot create resources.internal_immutable_snapshots.immutable: snapshot upload: No stub found for pattern: POST /api/2.0/repos/snapshots (501 <nil>)
         
        -=== Break the glass out of band
        ->>> [CLI] api post /api/2.0/snapshots:breakGlass --json {"snapshot_content_path": "/Workspace/Users/[UUID]/.snapshots/[SNAPSHOT_HASH]/[SNAPSHOT_HASH]-[UUID]/snapshot"}
        -true
        +Endpoint: POST [DATABRICKS_URL]/api/2.0/repos/snapshots
        +HTTP Status: 501 Not Implemented
        +API error_code: <nil>
        +API message: No stub found for pattern: POST /api/2.0/repos/snapshots
         
        -=== Deploy without --force fails
        ->>> musterr [CLI] bundle deploy
        -Error: the last deployment was modified in the workspace. Changes might be overwritten by this deployment. To confirm it, use the --force flag
        +Error: cannot create resources.jobs.my_job: dependency failed: resources.internal_immutable_snapshots.immutable
         
         Files: 0 uploaded, 0 deleted
         
        -=== Deploy with --force moves to a new snapshot
        ->>> [CLI] bundle deploy --force
        -Recreated internal_immutable_snapshots.immutable
        -Updated jobs.my_job
        -Files: 0 uploaded, 0 deleted
        -Resources: 1 created, 1 changed, 1 deleted, 0 unchanged
        -Second snapshot path: /Workspace/Users/[UUID]/.snapshots/[SNAPSHOT_HASH]/[SNAPSHOT_HASH]-[UUID]/snapshot/files/src/main.py
        -OK: --force created a new snapshot path
        -
        -=== Redeploy reuses the new snapshot
        ->>> [CLI] bundle deploy
        -Files: 0 uploaded, 0 deleted
        -Resources: 0 created, 0 changed, 0 deleted, 2 unchanged
        -Third snapshot path: /Workspace/Users/[UUID]/.snapshots/[SNAPSHOT_HASH]/[SNAPSHOT_HASH]-[UUID]/snapshot/files/src/main.py
        -OK: new snapshot reused on redeploy
        -
        -=== Save a plan for a content change, then break the glass before deploying it
        ->>> [CLI] bundle plan -o json
        -
        ->>> [CLI] api post /api/2.0/snapshots:breakGlass --json {"snapshot_content_path": "/Workspace/Users/[UUID]/.snapshots/[SNAPSHOT_HASH]/[SNAPSHOT_HASH]-[UUID]/snapshot"}
        -true
        -
        -=== Deploying the saved plan without --force fails
        ->>> musterr [CLI] bundle deploy --plan plan.json
        -Error: the last deployment was modified in the workspace. Changes might be overwritten by this deployment. To confirm it, use the --force flag
        -
        -Files: 0 uploaded, 0 deleted
        -
        -=== Deploying the saved plan with --force moves to the planned snapshot
        ->>> [CLI] bundle deploy --plan plan.json --force
        -Recreated internal_immutable_snapshots.immutable
        -Updated jobs.my_job
        -Files: 0 uploaded, 0 deleted
        -Resources: 1 created, 1 changed, 1 deleted, 0 unchanged
        -Fourth snapshot path: /Workspace/Users/[UUID]/.snapshots/[SNAPSHOT_HASH]/[SNAPSHOT_HASH]-[UUID]/snapshot/files/src/main.py
        -OK: the saved plan moved the deployment to a new snapshot
        -
         >>> [CLI] bundle destroy --auto-approve
        -The following resources will be deleted:
        -  delete resources.jobs.my_job
        -
         All files and directories at the following location will be deleted: /Workspace/Users/[USERNAME]/.bundle/test-bundle-immutable-breakglass-[UNIQUE_NAME]/default
         
        -Destroy: 1 deleted
        +Destroy: 0 deleted
        +
        +Exit code: 1
TestAccept/bundle/deploy/immutable/can-manage/DMS=: branch ✅ | main (accb3df) ❌ | latest (v1.22.1) ❌

main (accb3df):

server.go:281: No handler for URL: /api/2.0/repos/snapshots
        Body: [2207 bytes] --635f3eb771ac96d080c50443cbafd174e9789abd551a65b6326d1c889a83
        Content-Disposition: form-data; name="snapshot_id"
        
        962f29007dc86ff712090c2e2de926d7771722018e5d436f49d000e27eff5d97
        --635f3eb771ac96d080c50443cbafd174e9789abd551a65b6326d1c889a83
        Content-Disposition: form-data; name="bundle_id"
        
        ca6300e8dd75bc3e5d0a7d132a75d444c5dc7a42401bf8df2ef9933d245a42ac
        --635f3eb771ac96d080c50443cbafd174e9789abd551a65b6326d1c889a83
        Content-Disposition: form-data; name="access_control_list"
        
        [{"user_name":"aaaaaaaa-bbbb-4ccc-dddd-eeeeeeeeeeee","permission_level":"CAN_READ"},{"user_name":"deco-test-user@databricks.com","permission_level":"CAN_READ"}]
        --635f3eb771ac96d080c50443cbafd174e9789abd551a65b6326d1c889a83
        Content-Disposition: form-data; name="file"; filename="snapshot.zip"
        Content-Type: application/zip
        
        PK����������!(��������������	�files/databricks.ymlUT����Cm8|��N�0���~�Q�n��g���B��+X�L��o�����Ih�J�M�3���[�h=
        ��U@��K��]��*���yPQ� ���Ko��4���ѴuN7��!c���\�X��9$o��Tj�XF
        ���b�����z��Ǔ|>��O����$�ֲh�_�u�ު�493��I�1���\��I/_�0�s������܁ͪ������C�8�(Y�(�\_S�ݾPp;�FtmK��(`�(d�A����7��(��X��'v3�Q���\�_ArB*.E�������PK���Q��
        �������PK����������!(��������������	�files/databricks.yml.tmplUT����Cm8|��n� ���<�*ʕ��Y�P����&9#�lZbX�`�~�
        �M�F�\l�~3,4=�-
        �@ڡ��)���ƹ>��"o5q�I�!_����I���K��#`4�)k[Jn�u���Q@�=2�0:���
        ���V���V����$����F5/�>��Q���U�}�{f,b�}lqj��f���Q]}3�����X��S��E|2T����t�T��'U�����{E������6��ۭӆ6a��!
&z*�3��4��я���������U����x����b���PK��"3����������PK����������!(��������������	�files/src/main.pyUT����Cm8�'���print("Hello from Spark Python Task!")
        ��PK�����'.���'���PK����������!(������������"�	�.databricks/snapshot-metadata.jsonUT����Cm8�W���{"permissions_hash":"8cbff342214bd1b8d3d6120b10cd8a2e62c6a04998aa7eb1a94ede0f07487789"}��PK������^���W���PK������������!(�Q��
        ���������	���������������files/databricks.ymlUT����Cm8PK������������!("3������������	�����������U���files/databricks.yml.tmplUT����Cm8PK������������!(���'.���'�����	���������������files/src/main.pyUT����Cm8PK������������!(����^���W���"�	���������������.databricks/snapshot-metadata.jsonUT����Cm8PK����������<���������
        --635f3eb771ac96d080c50443cbafd174e9789abd551a65b6326d1c889a83--
        
        
        For acceptance tests, add this to test.toml:
        [[Server]]
        Pattern = "POST /api/2.0/repos/snapshots"
        Response.Body = '<response body here>'
        # Response.StatusCode = <response code if not 200>
    acceptance_test.go:1311: Diff:
        --- bundle/deploy/immutable/can-manage/output.txt
        +++ /tmp/TestAcceptbundledeployimmutablecan-manageDMS=1321192008/002/output.txt
        @@ -13,23 +13,19 @@
         See https://docs.databricks.com/dev-tools/bundles/permissions.html to learn more about permission configuration.
           in databricks.yml:8:3
         
        -Created internal_immutable_snapshots.immutable
        -Created jobs.my_job
        -Created jobs.my_job.permissions
        -Files: 0 uploaded, 0 deleted
        -Resources: 3 created, 0 changed, 0 deleted, 0 unchanged
        +Error: cannot create resources.internal_immutable_snapshots.immutable: snapshot upload: No stub found for pattern: POST /api/2.0/repos/snapshots (501 <nil>)
         
        -=== Check can_manage_principals sent to the snapshot create API
        ->>> print_requests.py //api/2.0/snapshots
        -[
        -  {
        -    "service_principal_name": "[USERNAME]"
        -  },
        -  {
        -    "user_name": "deco-test-user@databricks.com"
        -  }
        -]
        +Endpoint: POST [DATABRICKS_URL]/api/2.0/repos/snapshots
        +HTTP Status: 501 Not Implemented
        +API error_code: <nil>
        +API message: No stub found for pattern: POST /api/2.0/repos/snapshots
         
        +Error: cannot create resources.jobs.my_job: dependency failed: resources.internal_immutable_snapshots.immutable
        +
        +Error: cannot create resources.jobs.my_job.permissions: dependency failed: resources.internal_immutable_snapshots.immutable
        +
        +Files: 0 uploaded, 0 deleted
        +
         >>> [CLI] bundle destroy --auto-approve
         Recommendation: permissions section should explicitly include the current deployment identity '[USERNAME]' or one of its groups
         If it is not included, CAN_MANAGE permissions are only applied if the present identity is used to deploy.
        @@ -43,9 +37,8 @@
         See https://docs.databricks.com/dev-tools/bundles/permissions.html to learn more about permission configuration.
           in databricks.yml:8:3
         
        -The following resources will be deleted:
        -  delete resources.jobs.my_job
        -
         All files and directories at the following location will be deleted: /Workspace/Users/[USERNAME]/.bundle/test-bundle-immutable-can-manage-[UNIQUE_NAME]/default
         
        -Destroy: 1 deleted
        +Destroy: 0 deleted
        +
        +Exit code: 1

latest (v1.22.1):

server.go:281: No handler for URL: /api/2.0/repos/snapshots
        Body: [2208 bytes] --7b496e0c398792b1f1529b4bbc8a3ed80b2c7833d1737a7cdac90f149dbd
        Content-Disposition: form-data; name="snapshot_id"
        
        370f981357e6a6d39c0585590072e5fe21398192151b891645dce8f931281510
        --7b496e0c398792b1f1529b4bbc8a3ed80b2c7833d1737a7cdac90f149dbd
        Content-Disposition: form-data; name="bundle_id"
        
        d4314f38226c03f3835f558e0e6965664b86d56b6e824bc4c5fcbb433d9a3f72
        --7b496e0c398792b1f1529b4bbc8a3ed80b2c7833d1737a7cdac90f149dbd
        Content-Disposition: form-data; name="access_control_list"
        
        [{"user_name":"aaaaaaaa-bbbb-4ccc-dddd-eeeeeeeeeeee","permission_level":"CAN_READ"},{"user_name":"deco-test-user@databricks.com","permission_level":"CAN_READ"}]
        --7b496e0c398792b1f1529b4bbc8a3ed80b2c7833d1737a7cdac90f149dbd
        Content-Disposition: form-data; name="file"; filename="snapshot.zip"
        Content-Type: application/zip
        
        PK����������!(��������������	�files/databricks.ymlUT����Cm8|��N�0���~�U�n%(�|�B��}��q6��^[�	��#'��*1�D�ߎ��
        ���� �P@Ɣ�br�\ɪ�ȵ"���w�C����LJ�<��g��})������F㐲�-�� �o{��r,�X��LJ�Sj����Z�χ�|;���/��$�r�գ�|��̧^e�E�Ǵ��1�1��5�q'��_�W��w����]m�je�ƕm�!G��RPq����O���
        ng׈�ui0��lw)�S������&�=��Z�D����W��V�R@}����	c2��l���5�PK��/.h���������PK����������!(��������������	�files/databricks.yml.tmplUT����Cm8|��n� ���<�*ʕ��Y�P����&9#�lZbX�`�~�
        �M�F�\l�~3,4=�-
        �@ڡ��)���ƹ>��"o5q�I�!_����I���K��#`4�)k[Jn�u���Q@�=2�0:���
        ���V���V����$����F5/�>��Q���U�}�{f,b�}lqj��f���Q]}3�����X��S��E|2T����t�T��'U�����{E������6��ۭӆ6a��!
&z*�3��4��я���������U����x����b���PK��"3����������PK����������!(��������������	�files/src/main.pyUT����Cm8�'���print("Hello from Spark Python Task!")
        ��PK�����'.���'���PK����������!(������������"�	�.databricks/snapshot-metadata.jsonUT����Cm8�W���{"permissions_hash":"8cbff342214bd1b8d3d6120b10cd8a2e62c6a04998aa7eb1a94ede0f07487789"}��PK������^���W���PK������������!(/.h�����������	���������������files/databricks.ymlUT����Cm8PK������������!("3������������	�����������V���files/databricks.yml.tmplUT����Cm8PK������������!(���'.���'�����	���������������files/src/main.pyUT����Cm8PK������������!(����^���W���"�	���������������.databricks/snapshot-metadata.jsonUT����Cm8PK����������<���������
        --7b496e0c398792b1f1529b4bbc8a3ed80b2c7833d1737a7cdac90f149dbd--
        
        
        For acceptance tests, add this to test.toml:
        [[Server]]
        Pattern = "POST /api/2.0/repos/snapshots"
        Response.Body = '<response body here>'
        # Response.StatusCode = <response code if not 200>
    acceptance_test.go:1311: Diff:
        --- bundle/deploy/immutable/can-manage/output.txt
        +++ /tmp/TestAcceptbundledeployimmutablecan-manageDMS=3213396400/002/output.txt
        @@ -13,23 +13,19 @@
         See https://docs.databricks.com/dev-tools/bundles/permissions.html to learn more about permission configuration.
           in databricks.yml:8:3
         
        -Created internal_immutable_snapshots.immutable
        -Created jobs.my_job
        -Created jobs.my_job.permissions
        -Files: 0 uploaded, 0 deleted
        -Resources: 3 created, 0 changed, 0 deleted, 0 unchanged
        +Error: cannot create resources.internal_immutable_snapshots.immutable: snapshot upload: No stub found for pattern: POST /api/2.0/repos/snapshots (501 <nil>)
         
        -=== Check can_manage_principals sent to the snapshot create API
        ->>> print_requests.py //api/2.0/snapshots
        -[
        -  {
        -    "service_principal_name": "[USERNAME]"
        -  },
        -  {
        -    "user_name": "deco-test-user@databricks.com"
        -  }
        -]
        +Endpoint: POST [DATABRICKS_URL]/api/2.0/repos/snapshots
        +HTTP Status: 501 Not Implemented
        +API error_code: <nil>
        +API message: No stub found for pattern: POST /api/2.0/repos/snapshots
         
        +Error: cannot create resources.jobs.my_job: dependency failed: resources.internal_immutable_snapshots.immutable
        +
        +Error: cannot create resources.jobs.my_job.permissions: dependency failed: resources.internal_immutable_snapshots.immutable
        +
        +Files: 0 uploaded, 0 deleted
        +
         >>> [CLI] bundle destroy --auto-approve
         Recommendation: permissions section should explicitly include the current deployment identity '[USERNAME]' or one of its groups
         If it is not included, CAN_MANAGE permissions are only applied if the present identity is used to deploy.
        @@ -43,9 +37,8 @@
         See https://docs.databricks.com/dev-tools/bundles/permissions.html to learn more about permission configuration.
           in databricks.yml:8:3
         
        -The following resources will be deleted:
        -  delete resources.jobs.my_job
        -
         All files and directories at the following location will be deleted: /Workspace/Users/[USERNAME]/.bundle/test-bundle-immutable-can-manage-[UNIQUE_NAME]/default
         
        -Destroy: 1 deleted
        +Destroy: 0 deleted
        +
        +Exit code: 1
TestAccept/bundle/deploy/immutable/destroy-redeploy/DMS=: branch ✅ | main (accb3df) ❌ | latest (v1.22.1) ❌

main (accb3df):

acceptance_test.go:1311: Diff:
        --- bundle/deploy/immutable/destroy-redeploy/output.txt
        +++ /tmp/TestAcceptbundledeployimmutabledestroy-redeployDMS=2534048508/002/output.txt
        @@ -1,58 +1,20 @@
         
         === Deploy the immutable snapshot
         >>> [CLI] bundle deploy
        -Created internal_immutable_snapshots.immutable
        -Created jobs.my_job
        -Files: 0 uploaded, 0 deleted
        -Resources: 2 created, 0 changed, 0 deleted, 0 unchanged
        -First snapshot path: /Workspace/Users/[UUID]/.snapshots/[SNAPSHOT_HASH]/[SNAPSHOT_HASH]-[UUID]/snapshot/files/src/main.py
        +Error: cannot create resources.internal_immutable_snapshots.immutable: snapshot upload: No stub found for pattern: POST /api/2.0/repos/snapshots (501 <nil>)
         
        -=== Destroy the bundle
        ->>> [CLI] bundle destroy --auto-approve
        -The following resources will be deleted:
        -  delete resources.jobs.my_job
        +Endpoint: POST [DATABRICKS_URL]/api/2.0/repos/snapshots
        +HTTP Status: 501 Not Implemented
        +API error_code: <nil>
        +API message: No stub found for pattern: POST /api/2.0/repos/snapshots
         
        -All files and directories at the following location will be deleted: /Workspace/Users/[USERNAME]/.bundle/test-bundle-immutable-redeploy-[UNIQUE_NAME]/default
        +Error: cannot create resources.jobs.my_job: dependency failed: resources.internal_immutable_snapshots.immutable
         
        -Destroy: 1 deleted
        -
        -=== Deploy again moves to a new snapshot instead of the one left behind
        ->>> [CLI] bundle deploy
        -Created internal_immutable_snapshots.immutable
        -Created jobs.my_job
         Files: 0 uploaded, 0 deleted
        -Resources: 2 created, 0 changed, 0 deleted, 0 unchanged
        -Second snapshot path: /Workspace/Users/[UUID]/.snapshots/[SNAPSHOT_HASH]/[SNAPSHOT_HASH]-[UUID]/snapshot/files/src/main.py
        -OK: deployment moved to a new snapshot
         
        -=== Redeploy reuses the new snapshot
        ->>> [CLI] bundle deploy
        -Files: 0 uploaded, 0 deleted
        -Resources: 0 created, 0 changed, 0 deleted, 2 unchanged
        -Third snapshot path: /Workspace/Users/[UUID]/.snapshots/[SNAPSHOT_HASH]/[SNAPSHOT_HASH]-[UUID]/snapshot/files/src/main.py
        -OK: new snapshot reused on redeploy
        -
        -=== Destroy and deploy again moves to yet another snapshot
         >>> [CLI] bundle destroy --auto-approve
        -The following resources will be deleted:
        -  delete resources.jobs.my_job
        -
         All files and directories at the following location will be deleted: /Workspace/Users/[USERNAME]/.bundle/test-bundle-immutable-redeploy-[UNIQUE_NAME]/default
         
        -Destroy: 1 deleted
        +Destroy: 0 deleted
         
        ->>> [CLI] bundle deploy
        -Created internal_immutable_snapshots.immutable
        -Created jobs.my_job
        -Files: 0 uploaded, 0 deleted
        -Resources: 2 created, 0 changed, 0 deleted, 0 unchanged
        -Fourth snapshot path: /Workspace/Users/[UUID]/.snapshots/[SNAPSHOT_HASH]/[SNAPSHOT_HASH]-[UUID]/snapshot/files/src/main.py
        -OK: deployment moved to a new snapshot
        -
        ->>> [CLI] bundle destroy --auto-approve
        -The following resources will be deleted:
        -  delete resources.jobs.my_job
        -
        -All files and directories at the following location will be deleted: /Workspace/Users/[USERNAME]/.bundle/test-bundle-immutable-redeploy-[UNIQUE_NAME]/default
        -
        -Destroy: 1 deleted
        +Exit code: 1

latest (v1.22.1): same output as main (accb3df)

TestAccept/bundle/deploy/immutable/dev-mode/DMS=: branch ✅ | main (accb3df) ❌ | latest (v1.22.1) ❌

main (accb3df):

acceptance_test.go:1311: Diff:
        --- bundle/deploy/immutable/dev-mode/output.txt
        +++ /tmp/TestAcceptbundledeployimmutabledev-modeDMS=787392409/002/output.txt
        @@ -18,21 +18,20 @@
         Validation OK!
         
         >>> [CLI] bundle deploy -t dev
        -Created internal_immutable_snapshots.immutable
        -Created jobs.my_job
        -Files: 0 uploaded, 0 deleted
        -Resources: 2 created, 0 changed, 0 deleted, 0 unchanged
        +Error: cannot create resources.internal_immutable_snapshots.immutable: snapshot upload: No stub found for pattern: POST /api/2.0/repos/snapshots (501 <nil>)
         
        ->>> [CLI] jobs get [MY_JOB_ID]
        -{
        -  "name": "[dev [USERNAME]] my job",
        -  "python_file": "/Workspace/Users/[UUID]/.snapshots/[SNAPSHOT_HASH]/[SNAPSHOT_HASH]-[UUID]/snapshot/files/src/main.py"
        -}
        +Endpoint: POST [DATABRICKS_URL]/api/2.0/repos/snapshots
        +HTTP Status: 501 Not Implemented
        +API error_code: <nil>
        +API message: No stub found for pattern: POST /api/2.0/repos/snapshots
         
        ->>> [CLI] bundle destroy -t dev --auto-approve
        -The following resources will be deleted:
        -  delete resources.jobs.my_job
        +Error: cannot create resources.jobs.my_job: dependency failed: resources.internal_immutable_snapshots.immutable
         
        +Files: 0 uploaded, 0 deleted
        +
        +>>> [CLI] bundle destroy -t dev --auto-approve
         All files and directories at the following location will be deleted: /Workspace/Users/[USERNAME]/.bundle/test-bundle-immutable-dev-mode-[UNIQUE_NAME]/dev
         
        -Destroy: 1 deleted
        +Destroy: 0 deleted
        +
        +Exit code: 1

latest (v1.22.1): same output as main (accb3df)

TestAccept/bundle/deploy/immutable/legacy-state/DMS=: branch ✅ | main (accb3df) ❌ | latest (v1.22.1) ❌

main (accb3df):

acceptance_test.go:1311: Diff:
        --- bundle/deploy/immutable/legacy-state/output.txt
        +++ /tmp/TestAcceptbundledeployimmutablelegacy-stateDMS=1798871373/002/output.txt
        @@ -1,34 +1,20 @@
         
         === Deploy an immutable snapshot
         >>> [CLI] bundle deploy
        -Created internal_immutable_snapshots.immutable
        -Created jobs.my_job
        -Files: 0 uploaded, 0 deleted
        -Resources: 2 created, 0 changed, 0 deleted, 0 unchanged
        +Error: cannot create resources.internal_immutable_snapshots.immutable: snapshot upload: No stub found for pattern: POST /api/2.0/repos/snapshots (501 <nil>)
         
        -=== Rewrite the state the way a CLI without this feature wrote it
        -=== Deploying on top of that state succeeds and moves to the current layout
        ->>> [CLI] bundle deploy
        -Recreated internal_immutable_snapshots.immutable
        -Updated jobs.my_job
        -Files: 0 uploaded, 0 deleted
        -Resources: 1 created, 1 changed, 1 deleted, 0 unchanged
        -Snapshot path: /Workspace/Users/[UUID]/.snapshots/[SNAPSHOT_HASH]/[SNAPSHOT_HASH]-[UUID]/snapshot/files/src/main.py
        -OK: deployed to the current snapshot layout
        +Endpoint: POST [DATABRICKS_URL]/api/2.0/repos/snapshots
        +HTTP Status: 501 Not Implemented
        +API error_code: <nil>
        +API message: No stub found for pattern: POST /api/2.0/repos/snapshots
         
        -=== The check still applies to a deployment carried over from the older layout
        ->>> [CLI] api post /api/2.0/snapshots:breakGlass --json {"snapshot_content_path": "/Workspace/Users/[UUID]/.snapshots/[SNAPSHOT_HASH]/[SNAPSHOT_HASH]-[UUID]/snapshot"}
        -true
        +Error: cannot create resources.jobs.my_job: dependency failed: resources.internal_immutable_snapshots.immutable
         
        ->>> musterr [CLI] bundle deploy
        -Error: the last deployment was modified in the workspace. Changes might be overwritten by this deployment. To confirm it, use the --force flag
        -
         Files: 0 uploaded, 0 deleted
         
         >>> [CLI] bundle destroy --auto-approve
        -The following resources will be deleted:
        -  delete resources.jobs.my_job
        -
         All files and directories at the following location will be deleted: /Workspace/Users/[USERNAME]/.bundle/test-bundle-immutable-legacy-[UNIQUE_NAME]/default
         
        -Destroy: 1 deleted
        +Destroy: 0 deleted
        +
        +Exit code: 1

latest (v1.22.1): same output as main (accb3df)

TestAccept/bundle/deploy/immutable/missing-snapshot/DMS=: branch ✅ | main (accb3df) ❌ | latest (v1.22.1) ❌

main (accb3df):

acceptance_test.go:1311: 
        	Error Trace:	/home/runner/work/cli/cli/libs/testdiff/testdiff.go:22
        	            				/home/runner/work/cli/cli/acceptance/acceptance_test.go:1311
        	            				/home/runner/work/cli/cli/acceptance/acceptance_test.go:1081
        	            				/home/runner/work/cli/cli/acceptance/acceptance_test.go:659
        	Error:      	Not equal: 
        	            	expected: "\n=== Deploy an immutable snapshot\n>>> [CLI] bundle deploy\nCreated internal_immutable_snapshots.immutable\nCreated jobs.my_job\nFiles: 0 uploaded, 0 deleted\nResources: 2 created, 0 changed, 0 deleted, 0 unchanged\n\n=== Point the state at a snapshot that is not there\n=== Deploying still works instead of failing on the snapshot that is not there\n>>> [CLI] bundle deploy\nRecreated internal_immutable_snapshots.immutable\nUpdated jobs.my_job\nFiles: 0 uploaded, 0 deleted\nResources: 1 created, 1 changed, 1 deleted, 0 unchanged\n\n>>> [CLI] bundle destroy --auto-approve\nThe following resources will be deleted:\n  delete resources.jobs.my_job\n\nAll files and directories at the following location will be deleted: /Workspace/Users/[USERNAME]/.bundle/test-bundle-immutable-missing-[UNIQUE_NAME]/default\n\nDestroy: 1 deleted\n"
        	            	actual  : "\n=== Deploy an immutable snapshot\n>>> [CLI] bundle deploy\nError: cannot create resources.internal_immutable_snapshots.immutable: snapshot upload: No stub found for pattern: POST /api/2.0/repos/snapshots (501 <nil>)\n\nEndpoint: POST [DATABRICKS_URL]/api/2.0/repos/snapshots\nHTTP Status: 501 Not Implemented\nAPI error_code: <nil>\nAPI message: No stub found for pattern: POST /api/2.0/repos/snapshots\n\nError: cannot create resources.jobs.my_job: dependency failed: resources.internal_immutable_snapshots.immutable\n\nFiles: 0 uploaded, 0 deleted\n\n>>> [CLI] bundle destroy --auto-approve\nAll files and directories at the following location will be deleted: /Workspace/Users/[USERNAME]/.bundle/test-bundle-immutable-missing-[UNIQUE_NAME]/default\n\nDestroy: 0 deleted\n\nExit code: 1\n"
        	            	
        	            	Diff:
        	            	--- Expected
        	            	+++ Actual
        	            	@@ -3,22 +3,19 @@
        	            	 >>> [CLI] bundle deploy
        	            	-Created internal_immutable_snapshots.immutable
        	            	-Created jobs.my_job
        	            	+Error: cannot create resources.internal_immutable_snapshots.immutable: snapshot upload: No stub found for pattern: POST /api/2.0/repos/snapshots (501 <nil>)
        	            	+
        	            	+Endpoint: POST [DATABRICKS_URL]/api/2.0/repos/snapshots
        	            	+HTTP Status: 501 Not Implemented
        	            	+API error_code: <nil>
        	            	+API message: No stub found for pattern: POST /api/2.0/repos/snapshots
        	            	+
        	            	+Error: cannot create resources.jobs.my_job: dependency failed: resources.internal_immutable_snapshots.immutable
        	            	+
        	            	 Files: 0 uploaded, 0 deleted
        	            	-Resources: 2 created, 0 changed, 0 deleted, 0 unchanged
        	            	-
        	            	-=== Point the state at a snapshot that is not there
        	            	-=== Deploying still works instead of failing on the snapshot that is not there
        	            	->>> [CLI] bundle deploy
        	            	-Recreated internal_immutable_snapshots.immutable
        	            	-Updated jobs.my_job
        	            	-Files: 0 uploaded, 0 deleted
        	            	-Resources: 1 created, 1 changed, 1 deleted, 0 unchanged
        	            	 
        	            	 >>> [CLI] bundle destroy --auto-approve
        	            	-The following resources will be deleted:
        	            	-  delete resources.jobs.my_job
        	            	-
        	            	 All files and directories at the following location will be deleted: /Workspace/Users/[USERNAME]/.bundle/test-bundle-immutable-missing-[UNIQUE_NAME]/default
        	            	 
        	            	-Destroy: 1 deleted
        	            	+Destroy: 0 deleted
        	            	 
        	            	+Exit code: 1
        	            	+
        	Test:       	TestAccept/bundle/deploy/immutable/missing-snapshot/DMS=
        	Messages:   	bundle/deploy/immutable/missing-snapshot/output.txt vs /tmp/TestAcceptbundledeployimmutablemissing-snapshotDMS=2164503439/002/output.txt

latest (v1.22.1): same output as main (accb3df)

TestAccept/bundle/deploy/immutable/no-artifacts/DMS=/READPLAN=: branch ✅ | main (accb3df) ❌ | latest (v1.22.1) ❌

main (accb3df):

acceptance_test.go:1311: Diff:
        --- bundle/deploy/immutable/no-artifacts/output.txt
        +++ /tmp/TestAcceptbundledeployimmutableno-artifactsDMS=READPLAN=1254816899/002/output.txt
        @@ -15,16 +15,16 @@
           {
             "notebook_task": {
               "base_parameters": {
        -        "path": "/Workspace/Users/[UUID]/.snapshots/[SNAPSHOT_HASH]/[SNAPSHOT_HASH]-[UUID]/snapshot/files/some_path"
        +        "path": "/Workspace/Users/[UUID]/.snapshots/[SNAPSHOT_HASH]/[SNAPSHOT_HASH]/files/some_path"
               },
        -      "notebook_path": "/Workspace/Users/[UUID]/.snapshots/[SNAPSHOT_HASH]/[SNAPSHOT_HASH]-[UUID]/snapshot/files/src/notebook"
        +      "notebook_path": "/Workspace/Users/[UUID]/.snapshots/[SNAPSHOT_HASH]/[SNAPSHOT_HASH]/files/src/notebook"
             },
             "task_key": "notebook_task"
           },
           {
             "environment_key": "env",
             "spark_python_task": {
        -      "python_file": "/Workspace/Users/[UUID]/.snapshots/[SNAPSHOT_HASH]/[SNAPSHOT_HASH]-[UUID]/snapshot/files/src/main.py"
        +      "python_file": "/Workspace/Users/[UUID]/.snapshots/[SNAPSHOT_HASH]/[SNAPSHOT_HASH]/files/src/main.py"
             },
             "task_key": "spark_python_task"
           }
        @@ -35,8 +28,8 @@
           "action": "create",
           "new_state": {
             "value": {
        -      "relative_path": "[SNAPSHOT_HASH]/[SNAPSHOT_HASH]-[UUID]",
        -      "full_path": "/Workspace/Users/[UUID]/.snapshots/[SNAPSHOT_HASH]/[SNAPSHOT_HASH]-[UUID]/snapshot",
        +      "relative_path": "[SNAPSHOT_HASH]/[SNAPSHOT_HASH]",
        +      "full_path": "/Workspace/Users/[UUID]/.snapshots/[SNAPSHOT_HASH]/[SNAPSHOT_HASH]",
               "bundle_id": "[SNAPSHOT_HASH]",
               "acl": [
                 {
        @@ -44,101 +37,21 @@
                   "permission_level": "CAN_READ"
                 }
               ],
        -      "can_manage": [
        -        {
        -          "service_principal_name": "[USERNAME]"
        -        }
        -      ],
        -      "zip_path": "[TEST_TMP_DIR]/.databricks/bundle/default/snapshots/[SNAPSHOT_HASH]-[UUID].zip"
        +      "zip_path": "[TEST_TMP_DIR]/.databricks/bundle/default/snapshots/[SNAPSHOT_HASH].zip"
             }
           }
         }
         
         >>> [CLI] bundle deploy
        -Created internal_immutable_snapshots.immutable
        -Created jobs.my_job
        -Files: 0 uploaded, 0 deleted
        -Resources: 2 created, 0 changed, 0 deleted, 0 unchanged
        +Error: cannot create resources.internal_immutable_snapshots.immutable: snapshot upload: No stub found for pattern: POST /api/2.0/repos/snapshots (501 <nil>)
         
        ->>> jq .settings.tasks job.json
        -"/Workspace/Users/[UUID]/.snapshots/[SNAPSHOT_HASH]/[SNAPSHOT_HASH]-[UUID]/snapshot/files/src/main.py"
        +Endpoint: POST [DATABRICKS_URL]/api/2.0/repos/snapshots
        +HTTP Status: 501 Not Implemented
        +API error_code: <nil>
        +API message: No stub found for pattern: POST /api/2.0/repos/snapshots
         
        ->>> jq .settings.tasks job.json
        -"/Workspace/Users/[UUID]/.snapshots/[SNAPSHOT_HASH]/[SNAPSHOT_HASH]-[UUID]/snapshot/files/src/notebook"
        +Error: cannot create resources.jobs.my_job: dependency failed: resources.internal_immutable_snapshots.immutable
         
        ->>> jq .settings.tasks job.json
        -"/Workspace/Users/[UUID]/.snapshots/[SNAPSHOT_HASH]/[SNAPSHOT_HASH]-[UUID]/snapshot/files/some_path"
        -
        ->>> title Check snapshot plan after deploy: 
        -
        -=== Check snapshot plan after deploy: 
        ->>> [CLI] bundle plan -o json
        -
        ->>> jq .plan["resources.internal_immutable_snapshots.immutable"] plan.json
        -{
        -  "action": "skip",
        -  "remote_state": {
        -    "relative_path": "[SNAPSHOT_HASH]/[SNAPSHOT_HASH]-[UUID]",
        -    "full_path": "/Workspace/Users/[UUID]/.snapshots/[SNAPSHOT_HASH]/[SNAPSHOT_HASH]-[UUID]/snapshot"
        -  },
        -  "changes": {
        -    "acl": {
        -      "action": "skip",
        -      "reason": "missing_in_remote",
        -      "old": [
        -        {
        -          "user_name": "[USERNAME]",
        -          "permission_level": "CAN_READ"
        -        }
        -      ],
        -      "new": [
        -        {
        -          "user_name": "[USERNAME]",
        -          "permission_level": "CAN_READ"
        -        }
        -      ],
        -      "remote": null
        -    },
        -    "bundle_id": {
        -      "action": "skip",
        -      "reason": "missing_in_remote",
        -      "old": "[SNAPSHOT_HASH]",
        -      "new": "[SNAPSHOT_HASH]",
        -      "remote": ""
        -    },
        -    "can_manage": {
        -      "action": "skip",
        -      "reason": "missing_in_remote",
        -      "old": [
        -        {
        -          "service_principal_name": "[USERNAME]"
        -        }
        -      ],
        -      "new": [
        -        {
        -          "service_principal_name": "[USERNAME]"
        -        }
        -      ]
        -    },
        -    "zip_path": {
        -      "action": "skip",
        -      "reason": "missing_in_remote",
        -      "old": "[TEST_TMP_DIR]/.databricks/bundle/default/snapshots/[SNAPSHOT_HASH]-[UUID].zip",
        -      "new": "[TEST_TMP_DIR]/.databricks/bundle/default/snapshots/[SNAPSHOT_HASH]-[UUID].zip",
        -      "remote": ""
        -    }
        -  }
        -}
        -
        ->>> [CLI] bundle deploy
         Files: 0 uploaded, 0 deleted
        -Resources: 0 created, 0 changed, 0 deleted, 2 unchanged
        -Snapshot did not change as expected
         
        ->>> [CLI] bundle destroy --auto-approve
        -The following resources will be deleted:
        -  delete resources.jobs.my_job
        -
        -All files and directories at the following location will be deleted: /Workspace/Users/[USERNAME]/.bundle/test-bundle-immutable-no-artifacts-[UNIQUE_NAME]/default
        -
        -Destroy: 1 deleted
        +Exit code: 1
        
    acceptance_test.go:1130: Test produced unexpected files:
        plan.json

latest (v1.22.1): same output as main (accb3df)

9 more failure details omitted, see the full report in the run.

@denik

denik commented Oct 26, 2026

Copy link
Copy Markdown
Contributor

Immutable folders can be "break-glassed" in an emergency. In this case, CLI should prevent a normal deploy if the previously used snapshot was broken. With --force, it should allow to deploy to a new suffixed path and the deployments after should continue as normal

Why don't we make it normal behavior, without --force?

@andrewnester

Copy link
Copy Markdown
Contributor Author

@denik we don't want users accidentally overwrite any fixes made in breakglass version, hence it's an explicit --force action needed

Comment thread bundle/deploy/snapshot/upload.go Outdated
Comment thread bundle/deploy/snapshot/upload.go Outdated
Comment thread bundle/deploy/metadata/compute.go
@andrewnester
andrewnester added this pull request to the merge queue Oct 27, 2026
Merged via the queue into main with commit 8191901 Oct 27, 2026
28 checks passed
@andrewnester
andrewnester deleted the feat/immutable/breakglass branch October 27, 2026 12:47
@eng-dev-ecosystem-bot

Copy link
Copy Markdown
Collaborator

Integration test report

Commit: 8191901

Run: 40506670826

Env ❌​FAIL 🔄​flaky ✅​pass 🙈​skip Time
❌​ aws linux-2core-8gb 4 1463 1210 146:28
❌​ aws-windows-latest-4core-16gb 4 1388 1235 163:52
🔄​ azure linux-2core-8gb 4 1312 1262 117:59
🔄​ azure-windows-latest-4core-16gb 3 1238 1287 131:18
🔄​ gcp linux-2core-8gb 3 1300 1267 123:05
✅​ gcp-windows-latest-4core-16gb 1228 1292 138:45
12 interesting tests: 8 flaky, 4 FAIL
Test Name aws linux-2core-8gb aws-windows-latest-4core-16gb azure linux-2core-8gb azure-windows-latest-4core-16gb gcp linux-2core-8gb
❌​ TestAccept ❌​F ❌​F ✅​p 🔄​f 🔄​f
🔄​ TestAccept/bundle/resources/dashboards/simple ✅​p ✅​p 🔄​f ✅​p ✅​p
🔄​ TestAccept/bundle/resources/dashboards/simple/DMS=true ✅​p ✅​p 🔄​f ✅​p ✅​p
❌​ TestAccept/bundle/resources/postgres_databases/live_errors/bad_role_ref ❌​F ❌​F 🙈​s 🙈​s 🙈​s
❌​ TestAccept/bundle/resources/postgres_databases/live_errors/bad_role_ref/DMS= ❌​F ❌​F
❌​ TestAccept/bundle/resources/postgres_databases/live_errors/bad_role_ref/DMS=true ❌​F ❌​F
🔄​ TestAccept/bundle/resources/quality_monitors/change_assets_dir ✅​p ✅​p ✅​p ✅​p 🔄​f
🔄​ TestAccept/bundle/resources/quality_monitors/change_assets_dir/DMS= ✅​p ✅​p ✅​p ✅​p 🔄​f
🔄​ TestAccept/bundle/resources/quality_monitors/change_table_name ✅​p ✅​p ✅​p 🔄​f ✅​p
🔄​ TestAccept/bundle/resources/quality_monitors/change_table_name/DMS=true ✅​p ✅​p ✅​p 🔄​f ✅​p
🔄​ TestAccept/bundle/resources/schemas/auto-approve ✅​p ✅​p 🔄​f ✅​p ✅​p
🔄​ TestAccept/bundle/resources/schemas/auto-approve/DMS= ✅​p ✅​p 🔄​f ✅​p ✅​p
Top 50 slowest tests (at least 2 minutes):
duration env testname
13:18 gcp linux-2core-8gb TestAccept/bundle/resources/clusters/lifecycle-started/DMS=true
12:45 gcp linux-2core-8gb TestAccept/bundle/resources/clusters/lifecycle-started/DMS=
11:45 gcp-windows-latest-4core-16gb TestAccept/bundle/resources/apps/lifecycle-started/DMS=
11:14 gcp-windows-latest-4core-16gb TestAccept/bundle/resources/apps/lifecycle-started/DMS=true
10:09 aws-windows-latest-4core-16gb TestAccept/bundle/resources/clusters/lifecycle-started-toggle/DMS=
9:31 aws linux-2core-8gb TestAccept/bundle/resources/clusters/lifecycle-started-toggle/DMS=
9:21 gcp-windows-latest-4core-16gb TestAccept/bundle/resources/clusters/lifecycle-started/DMS=
9:08 aws-windows-latest-4core-16gb TestAccept/bundle/resources/clusters/lifecycle-started/DMS=
8:56 aws-windows-latest-4core-16gb TestAccept/bundle/deploy/spark-jar-task/DMS=true
8:40 aws linux-2core-8gb TestAccept/bundle/deploy/spark-jar-task/DMS=true
8:38 aws-windows-latest-4core-16gb TestAccept/bundle/deploy/spark-jar-task/DMS=
8:24 aws linux-2core-8gb TestAccept/bundle/resources/apps/lifecycle-started/DMS=
8:21 aws linux-2core-8gb TestAccept/bundle/resources/apps/lifecycle-started/DMS=true
8:09 gcp-windows-latest-4core-16gb TestAccept/bundle/resources/clusters/lifecycle-started/DMS=true
8:03 gcp-windows-latest-4core-16gb TestAccept/bundle/resources/clusters/deploy/local_ssd_count/DMS=true
7:52 aws linux-2core-8gb TestAccept/bundle/config-remote-sync/multiple_resources/DMS=true
7:51 aws-windows-latest-4core-16gb TestAccept/bundle/resources/apps/lifecycle-started/DMS=
7:50 aws linux-2core-8gb TestAccept/bundle/invariant/no_drift/DMS=/INPUT_CONFIG=cluster_apply_policy_default_values.yml.tmpl/READPLAN=1
7:42 gcp linux-2core-8gb TestAccept/bundle/resources/apps/lifecycle-started/DMS=
7:37 aws linux-2core-8gb TestAccept/bundle/resources/clusters/lifecycle-started/DMS=
7:36 aws-windows-latest-4core-16gb TestAccept/bundle/resources/clusters/lifecycle-started/DMS=true
7:34 aws-windows-latest-4core-16gb TestAccept/bundle/resources/apps/lifecycle-started/DMS=true
7:32 azure-windows-latest-4core-16gb TestAccept/bundle/resources/apps/lifecycle-started/DMS=
7:30 gcp-windows-latest-4core-16gb TestAccept/bundle/resources/clusters/deploy/local_ssd_count/DMS=
7:28 azure linux-2core-8gb TestAccept/bundle/config-remote-sync/multiple_resources/DMS=
7:22 gcp linux-2core-8gb TestAccept/bundle/resources/apps/lifecycle-started/DMS=true
7:20 gcp linux-2core-8gb TestAccept/bundle/invariant/delete_idempotent/DMS=/INPUT_CONFIG=cluster.yml.tmpl/READPLAN=1
7:19 azure-windows-latest-4core-16gb TestAccept/bundle/resources/apps/lifecycle-started/DMS=true
7:19 aws linux-2core-8gb TestAccept/bundle/invariant/delete_idempotent/DMS=/INPUT_CONFIG=cluster.yml.tmpl/READPLAN=
7:05 azure linux-2core-8gb TestAccept/bundle/config-remote-sync/multiple_resources/DMS=true
7:01 aws linux-2core-8gb TestAccept/bundle/invariant/destroy_idempotent/DMS=/INPUT_CONFIG=cluster_libraries.yml.tmpl/READPLAN=1
7:00 aws-windows-latest-4core-16gb TestAccept/bundle/resources/clusters/lifecycle-started-toggle/DMS=true
6:56 gcp linux-2core-8gb TestAccept/bundle/resources/clusters/deploy/local_ssd_count/DMS=true
6:51 azure linux-2core-8gb TestAccept/bundle/resources/apps/lifecycle-started/DMS=true
6:50 aws linux-2core-8gb TestAccept/bundle/invariant/destroy_idempotent/DMS=/INPUT_CONFIG=cluster.yml.tmpl/READPLAN=
6:48 aws-windows-latest-4core-16gb TestAccept/bundle/resources/clusters/deploy/simple/DMS=
6:41 aws linux-2core-8gb TestAccept/bundle/config-remote-sync/multiple_resources/DMS=
6:40 azure linux-2core-8gb TestAccept/bundle/resources/apps/lifecycle-started/DMS=
6:34 gcp linux-2core-8gb TestAccept/bundle/resources/clusters/deploy/local_ssd_count/DMS=
6:29 azure linux-2core-8gb TestAccept/bundle/resources/clusters/lifecycle-started/DMS=true
6:11 gcp linux-2core-8gb TestAccept/bundle/config-remote-sync/multiple_resources/DMS=
6:11 aws linux-2core-8gb TestAccept/bundle/invariant/destroy_idempotent/DMS=/INPUT_CONFIG=cluster_apply_policy_default_values.yml.tmpl/READPLAN=1
6:10 gcp linux-2core-8gb TestAccept/bundle/config-remote-sync/multiple_resources/DMS=true
5:58 gcp-windows-latest-4core-16gb TestAccept/bundle/resources/clusters/lifecycle-started-toggle/DMS=true
5:53 aws linux-2core-8gb TestAccept/bundle/resources/clusters/lifecycle-started/DMS=true
5:46 azure-windows-latest-4core-16gb TestAccept/bundle/resources/clusters/lifecycle-started/DMS=
5:32 azure-windows-latest-4core-16gb TestAccept/bundle/resources/clusters/lifecycle-started/DMS=true
5:22 aws linux-2core-8gb TestAccept/bundle/resources/clusters/lifecycle-started-toggle/DMS=true
5:21 azure linux-2core-8gb TestAccept/bundle/resources/clusters/lifecycle-started/DMS=
5:17 gcp linux-2core-8gb TestAccept/bundle/resources/clusters/lifecycle-started-toggle/DMS=true

deco-sdk-tagging Bot added a commit that referenced this pull request Oct 29, 2026
## Release v1.23.0

### CLI

 * Fix GitHub API rate limit errors in `aitools list` and plugin installs by pinning skills to `0.2.32`. ([#7159](#7159))
 * `databricks ssh connect` now makes `claude` and `codex` available on dedicated clusters. ([#7190](#7190))
 * `databricks ssh connect` on serverless now makes `claude` and `codex` available in IDE sessions (`--ide`) and to non-interactive commands (e.g. `databricks ssh connect -- 'claude -p "..."'`). ([#7123](#7123))

### AI Runtime

 * Add workload support for the GPU_1xRTX6000 accelerator type in enabled workspaces. ([#7214](#7214))
 * Show only the accelerator types available in the current workspace in `databricks air run -h config.compute`. ([#6993](#6993))

### Bundles

 * Fixed `bundle validate` failing with "expected a map to index" when a job `schedule`, `trigger` or `continuous` is a reference to a whole block, such as `${resources.jobs.base.schedule}`. ([#7225](#7225))
 * Added `lifecycle.depends_on` to order resources without referencing their fields. ([#7120](#7120))
 * Immutable-folder deploys now refuse to deploy onto a snapshot that was modified outside the bundle (break glass); `bundle deploy --force` moves the deployment to a fresh snapshot. ([#6774](#6774))
 * Fix `--include-locations` failing when a resource is missing a required field. ([#7185](#7185))
 * Removed spurious "required field is not set" warnings for a field whose value is a reference to a whole block, such as `schedule: ${resources.jobs.base.schedule}`. ([#7226](#7226))
 * Revert bundle file uploads to the legacy `/workspace-files/import-file` endpoint, rolling back [#6149](#6149) and [#7034](#7034) released in [v1.21.0](https://github.com/databricks/cli/releases/tag/v1.21.0). This fixes notebooks being uploaded as plain files and deployments failing (for example SQL notebooks in [#7216](#7216)). A remote file or notebook whose type differs from the local one is now deleted and replaced instead of blocking the deploy. ([#7218](#7218))
 * Support selecting resources for deletion with `bundle deploy --select`. ([#7023](#7023))
 * Add the `workspace.sync_mode` setting with the values `overwrite` (default), `in-place`, and `immutable`. It replaces `presets.source_linked_deployment` (use `in-place`) and `experimental.immutable_folder` (use `immutable`), which are now deprecated and emit a warning. ([#7183](#7183))

### Dependency Updates

 * Bump dependencies with known vulnerabilities. ([#7213](#7213))
 * Update the Go SDK to [v0.190.0](https://github.com/databricks/databricks-sdk-go/releases/tag/v0.190.0). ([#7155](#7155))
 * Update the Go SDK to [v0.191.0](https://github.com/databricks/databricks-sdk-go/releases/tag/v0.191.0). ([#7211](#7211))
 * Bump Node.js downloaded by the `ssh` agent shim from v24.21.0 to v24.22.2. ([#7246](#7246))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

DABs DABs related issues

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants